//============================================================================
// Copyright (C) 2010 Brett R. Jones
// All Rights Reserved
//
// You may redistribute and/or modify for non commercial and commercial uses
// provided this copyright notice remains in place and is not modified
//
// This code is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// brettjones1900@gmail.com
// http://www.p2panarchy.com
//============================================================================

#include "VxIrrLib.h"
#ifdef ANDROID_PLATFORM
	#include <jni.h>
#endif // ANDROID_PLATFORM

//============================================================================
//! global vars
//============================================================================
#ifdef ANDROID_PLATFORM
	extern JavaVM * 		GetJavaVM( void ); 			// function in app-android to get java virtual machine

	static JavaVM * 		g_poJavaVM = NULL;			// pointer to java virtual machine
	static jobject 			g_oSoundInterface;			// java side sound implementation

#endif // ANDROID_PLATFORM

//============================================================================
//! global functions
//============================================================================
#ifdef ANDROID_PLATFORM
//-----------------------------------------------------------------------------
//! call function in java code SoundInterface with string param
void SoundCallJavaStringFunction( const char * pFunctionName, const char * pStringParam )
{
	if( g_UserConfigImp.m_f32SoundVolume < 0.01 )
	{
		// no sound so dont bother
		return;
	}
	vx_assert( pStringParam );
	JNIEnv * poJniEnv;
	bool bIsAttached = false;
	//log_msg( 0, "SoundCallJavaStringFunction: getting jni env\n");

	// get java environment
	int status = g_poJavaVM->GetEnv((void **) &poJniEnv, JNI_VERSION_1_4);
	if(status < 0)
	{
		 // must attach to vm if called from a separate native thread
		log_msg( 0, "SoundCallJavaStringFunction: failed to get JNI environment... assuming native thread\n" );
		status = g_poJavaVM->AttachCurrentThread(&poJniEnv, NULL);
		if( status < 0 )
		{
			log_msg( 0, "SoundCallJavaStringFunction: failed to attach  to current thread\n" );
			return;
		}
		bIsAttached = true;
	}
	//log_msg( 0, "SoundCallJavaStringFunction: finding SoundInterface class\n");

	jclass jclassObj;
	jmethodID method;

	// get class in java code
	jclassObj = (poJniEnv)->FindClass("com/roguetreasure/destroytheworld/SoundInterface");
	if( NULL == jclassObj )
	{
		log_msg( 0, "SoundCallJavaStringFunction: failed to get class object\n");
		if( bIsAttached )
		{
			g_poJavaVM->DetachCurrentThread();
		}
		return;
	}
	//log_msg( 0, "SoundCallJavaStringFunction: getting method id of %s\n", pFunctionName );
	// get handle to function we want to call
	method = poJniEnv->GetStaticMethodID( jclassObj, pFunctionName, "(Ljava/lang/String;)V");
	if( ! method )
	{
		log_msg( 0, "SoundCallJavaStringFunction: failed to get method ID");
		if( bIsAttached )
		{
			g_poJavaVM->DetachCurrentThread();
		}
		return;
	}
	//log_msg( 0, "SoundCallJavaStringFunction: creating string parameter %s\n", pStringParam );
	// Construct a Java string
	jstring js = (poJniEnv)->NewStringUTF( pStringParam );

	log_msg( 0, "SoundCallJavaStringFunction: making call to java with sound %s\n", pStringParam );
	// make the call to the function in the java class
	(poJniEnv)->CallStaticVoidMethod( jclassObj, method, js );

	if( bIsAttached )
	{
		g_poJavaVM->DetachCurrentThread();
	}
	//log_msg( 0, "SoundCallJavaStringFunction: done\n");
}
//-----------------------------------------------------------------------------
//! call function in java code SoundInterface with float param
void SoundCallJavaFloatFunction( const char * pFunctionName, float f32Param )
{
	JNIEnv * poJniEnv;
	bool bIsAttached = false;
	log_msg( 0, "SoundCallJavaFloatFunction: getting jni env\n");

	// get java environment
	int status = g_poJavaVM->GetEnv((void **) &poJniEnv, JNI_VERSION_1_4);
	if(status < 0)
	{
		 // must attach to vm if called from a separate native thread
		log_msg( 0, "SoundCallJavaFloatFunction: failed to get JNI environment... assuming native thread\n" );
		status = g_poJavaVM->AttachCurrentThread(&poJniEnv, NULL);
		if( status < 0 )
		{
			log_msg( 0, "SoundCallJavaFloatFunction: failed to attach  to current thread\n" );
			return;
		}
		bIsAttached = true;
	}
	log_msg( 0, "SoundCallJavaFloatFunction: finding SoundInterface class\n");

	jclass jclassObj;
	jmethodID method;

	// get class in java code
	jclassObj = (poJniEnv)->FindClass("com/roguetreasure/destroytheworld/SoundInterface");
	if( NULL == jclassObj )
	{
		log_msg( 0, "SoundCallJavaFloatFunction: failed to get class object\n");
		if( bIsAttached )
		{
			g_poJavaVM->DetachCurrentThread();
		}
		return;
	}
	log_msg( 0, "SoundCallJavaFloatFunction: getting method id of %s\n", pFunctionName );
	// get handle to function we want to call
	method = poJniEnv->GetStaticMethodID( jclassObj, pFunctionName, "(F)V");
	if( ! method )
	{
		log_msg( 0, "SoundCallJavaFloatFunction: failed to get method ID");
		if( bIsAttached )
		{
			g_poJavaVM->DetachCurrentThread();
		}
		return;
	}
	log_msg( 0, "SoundCallJavaFloatFunction: making call to java\n");
	// make the call to the function in the java class
	(poJniEnv)->CallStaticVoidMethod( jclassObj, method, (jfloat)f32Param );

	if( bIsAttached )
	{
		g_poJavaVM->DetachCurrentThread();
	}
	log_msg( 0, "SoundCallJavaStringFunction: done\n");
}
#endif // ANDROID_PLATFORM

//! sound manager
//============================================================================
//----------------------------------------------------------------------------
//=== constructors ===//  
SoundMgr::SoundMgr()
{

}

//----------------------------------------------------------------------------
//! startup
RCODE SoundMgr::Startup( BOOL bEnabled )
{
	#ifdef ANDROID_PLATFORM
		//! get pointer to java virtual machine
		g_poJavaVM =  GetJavaVM();
		//! get global reference to SoundInterface on the java side
		// this will save having to get a reference each time we want to make a sound function call
	#endif

	RCODE rc = AudioBase::Startup( bEnabled );
	SfxSetVolume( g_UserConfigImp.m_f32SoundVolume );


	return rc;
}
//----------------------------------------------------------------------------
//! shutdown
void SoundMgr::Shutdown( void )
{
	AudioBase::Shutdown();
}

//============================================================================
//! background sound functions
//============================================================================
//----------------------------------------------------------------------------
//! call to play music ( background sound )
void SoundMgr::MusicPlay( const char * pSndFile )
{
	#ifdef ANDROID_PLATFORM
		// call android java code
		SoundCallJavaStringFunction( "MusicPlay", pSndFile );
	#else
		// openal implementation
	#endif
}
//----------------------------------------------------------------------------
//! call to pause music
void SoundMgr::MusicPause( const char * pSndFile )
{
	#ifdef ANDROID_PLATFORM
		// call android java code
		SoundCallJavaStringFunction( "MusicPause", pSndFile );
	#else
		// openal implementation
	#endif
}
//----------------------------------------------------------------------------
//! call to stop music
void SoundMgr::MusicStop( const char * pSndFile )
{
	#ifdef ANDROID_PLATFORM
		// call android java code
		SoundCallJavaStringFunction( "MusicStop", pSndFile );
	#else
		// openal implementation
	#endif
}
//----------------------------------------------------------------------------
//! call to set music volume
void SoundMgr::MusicSetVolume( float f32Volume )
{
	#ifdef ANDROID_PLATFORM
		// call android java code
		SoundCallJavaFloatFunction( "MusicSetVolume", f32Volume );
	#else
		// openal implementation
	#endif
}
//============================================================================
//! sound effect functions
//============================================================================
//----------------------------------------------------------------------------
//! call to play sfx ( sound effect )
void SoundMgr::SfxPlay( const char * pSndFile )
{
	#ifdef ANDROID_PLATFORM
		// call android java code
		SoundCallJavaStringFunction( "SfxPlay", pSndFile );
	#else
		// openal implementation
	#endif
}
//----------------------------------------------------------------------------
//! call to pause sfx
void SoundMgr::SfxPause( const char * pSndFile )
{
	#ifdef ANDROID_PLATFORM
		// call android java code
		SoundCallJavaStringFunction( "SfxPause", pSndFile );
	#else
		// openal implementation
	#endif
}
//----------------------------------------------------------------------------
//! call to stop sfx
void SoundMgr::SfxStop( const char * pSndFile )
{
	#ifdef ANDROID_PLATFORM
		// call android java code
		SoundCallJavaStringFunction( "SfxStop", pSndFile );
	#else
		// openal implementation
	#endif
}
//----------------------------------------------------------------------------
//! call to set sfx volume
void SoundMgr::SfxSetVolume( float f32Volume )
{
	#ifdef ANDROID_PLATFORM
		// call android java code
		SoundCallJavaFloatFunction( "SfxSetVolume", f32Volume );
	#else
		// openal implementation
	#endif
}
//============================================================================
//! cutscene movie functions
//============================================================================
//----------------------------------------------------------------------------
//! call to play movie ( game cutscene )
void SoundMgr::MoviePlay( const char * pSndFile )
{
	#ifdef ANDROID_PLATFORM
		// call android java code
		SoundCallJavaStringFunction( "MoviePlay", pSndFile );
	#else
		// openal implementation
	#endif
}
